/**
 * Project Name:template-web
 * File Name   :BaseDaoImpl.java
 * Package Name:org.cn.template.component.repository.impl
 * Date:2015年9月27日下午3:43:54
 * Copyright (c) 2015, http://my.oschina.net/httpssl All Rights Reserved.
 *
*/

package org.cn.template.component.repository.impl;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.cn.template.component.domain.PersistentModel;
import org.cn.template.component.ibatis.SqlMapId;
import org.cn.template.component.repository.IBaseDao;
import org.cn.template.component.repository.ISqlMap;
import org.cn.template.component.repository.ParamTools;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.util.Assert;

import com.google.common.collect.Maps;



/**
 * ClassName:BaseDaoImpl <br/>
 * Function :TODO ADD FUNCTION. <br/>
 * Reason	:TODO ADD REASON. <br/>
 * Date     :2015年9月27日 下午3:43:54 <br/>
 * @author  :http://my.oschina.net/httpssl
 * @email   :491835898@QQ.COM
 * @since   :JDK 1.7
 * @see 	 
 */
public abstract class BaseDaoImpl<T extends PersistentModel> extends AbstractSqlMapImpl<T> implements IBaseDao<T>
{
	/** 不能用于SQL中的非法字符（主要用于排序字段名） */
	public static final String[]	ILLEGAL_CHARS_FOR_SQL	= { ",", ";", " ", "\"", "%" };

	@Resource
	public ISqlMap					sqlMapClientTemplate;

	@Override
	public T insertOne(T model) throws Exception
	{
		// 当主键类型为String时,设置其值为uuid
		try {
			getJdbcTemplate().insert(getSqlName(SqlMapId.SQL_INSERT), model);
			return model;
		} catch (Exception e) {
			throw new Exception(String.format("添加对象出错！语句：%s", getSqlName(SqlMapId.SQL_INSERT)), e);
		}
	}

	private SqlMapClientTemplate getJdbcTemplate()
	{
		return sqlMapClientTemplate.getSqlMapClientTemplate();
	}

	@Override
	public void insertBatch(List<T> models) throws Exception
	{
		if (models != null && models.size() >= 1) {
			int size = 200;
			int batchSize = 0;
			if (models.size() % size == 0) {
				batchSize = models.size() / size;
			} else {
				batchSize = models.size() / size + 1;
			}
			for (int i = 0; i < batchSize; i++) {
				int startIndex = i * size;
				int endIndex = (i + 1) * size;
				if (endIndex > models.size()) {
					endIndex = models.size();
				}
				try {
					this.getJdbcTemplate().insert(getSqlName(SqlMapId.SQL_INSERTBATCH), models.subList(startIndex, endIndex));
				} catch (Exception e) {
					throw new Exception(String.format("添加对象出错！语句：%s", getSqlName(SqlMapId.SQL_INSERTBATCH)), e);
				}
			}
		}
	}

	@Override
	public int deleteById(@SuppressWarnings("rawtypes")Map param) throws Exception
	{
		try {
			return getJdbcTemplate().delete(getSqlName(SqlMapId.SQL_DELETE_BYID), param);
		} catch (Exception e) {
			throw new Exception(String.format("根据ID删除对象出错！语句：%s", getSqlName(SqlMapId.SQL_DELETE_BYID)), e);
		}
	}

	@Override
	public int delete(T param) throws Exception
	{
		try {
			return getJdbcTemplate().delete(getSqlName(SqlMapId.SQL_DELETE_ByParam), param);
		} catch (Exception e) {
			throw new Exception(String.format("根据删除对象出错！语句：%s", getSqlName(SqlMapId.SQL_DELETE_ByParam)), e);
		}
	}

	@Override
	public int updateById(T model) throws RuntimeException
	{
		try {
			return getJdbcTemplate().update(getSqlName(SqlMapId.SQL_UPDATE_ByPrimaryKey), model);
		} catch (Exception e) {
			throw new RuntimeException(String.format("根据ID更新对象出错！语句：%s", getSqlName(SqlMapId.SQL_UPDATE_ByPrimaryKey)), e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public <V extends T> V selectById(@SuppressWarnings("rawtypes")Map param) throws Exception
	{
		Assert.notNull(param);
		try {
			return (V) getJdbcTemplate().queryForObject(getSqlName(SqlMapId.SQL_SELECT_ByPrimaryKey), param);
		} catch (Exception e) {
			throw new Exception(String.format("根据ID查询对象出错！语句：%s", getSqlName(SqlMapId.SQL_SELECT_ByPrimaryKey)), e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public <V extends T> List<V> selectList(T query) throws Exception
	{
		try {
			Map params = ParamTools.toMap(query);
			return getJdbcTemplate().queryForList(getSqlName(SqlMapId.SQL_SELECT_LIST), params);
		} catch (Exception e) {
			throw new RuntimeException(String.format("查询对象列表出错！语句：%s", getSqlName(SqlMapId.SQL_SELECT_LIST)), e);
		}
	}

	@Override
	public Long selectListCount(T query) throws Exception
	{
		Map params = ParamTools.toMap(query);
		Object object = getJdbcTemplate().queryForObject(getSqlName(SqlMapId.SQL_SELECT_COUNT), params);
		if (object != null) {
			return (Long) object;
		}
		return 0L;
	}

	@SuppressWarnings("unchecked")
	@Override
	public <V extends T> V selectOne(T query) throws Exception
	{
		Assert.notNull(query);
		try {
			Map params = ParamTools.toMap(query);
			return (V) getJdbcTemplate().queryForObject(getSqlName(SqlMapId.SQL_SELECT_ByParam), params);
		} catch (Exception e) {
			throw new Exception(String.format("查询一条记录出错！语句：%s", getSqlName(SqlMapId.SQL_SELECT_ByParam)), e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public <V extends T> List<V> selectList(T query,@SuppressWarnings("rawtypes")Map page) throws Exception
	{
		Assert.notNull(query);
		try {
			return getJdbcTemplate().queryForList(getSqlName(SqlMapId.SQL_SELECT_LIST), getParams(query, page));
		} catch (Exception e) {
			throw new Exception(String.format("查询分页记录出错！语句：%s", getSqlName(SqlMapId.SQL_SELECT_LIST)), e);
		}
	}

	/**
	 * 分页查询
	 * 
	 * @param query
	 *            查询对象
	 * @param pageable
	 *            分页对象 group by order by limit offset,pageSize asc desc
	 */
	protected Map getParams(T query,@SuppressWarnings("rawtypes")Map pageable)
	{
		Map params = ParamTools.toMap(query, getRowBounds(pageable));
		if (pageable != null && pageable.get("sort") != null) {
			String sorting = pageable.get("sort").toString();
			params.put("sort", sorting.replace(":", ""));
		}
		return params;
	}

	protected Map getRowBounds(@SuppressWarnings("rawtypes")Map pageable)
	{
		Map<String, Object> bounds = Maps.newConcurrentMap();
		if (pageable != null && pageable.size() > 0) {
			bounds.putAll(pageable);
		}
		return bounds;
	}

	@SuppressWarnings("unchecked")
	@Override
	public <V extends T> List<V> selectList(String statement,Map<String,?> paramMap) throws Exception
	{
		return getJdbcTemplate().queryForList(getSqlName(statement),paramMap);
	}

	@Override
	public List<?> selectMapList(String statement,Map<String,?> paramMap) throws Exception
	{
		return getJdbcTemplate().queryForList(getSqlName(statement),paramMap);
	}
	
	/**
	 * 用于分页
	 */
	@Override
	public List<?> getList(String statement, Map<String,?> param) throws Exception
	{
		try {
			return getJdbcTemplate().queryForList(getSqlName(statement), param);
		} catch (Exception e) {
			throw new Exception(String.format("查询分页记录出错！ %s", e.getMessage()));
		}
	}
	/**
	 * 用于分页
	 */
	@Override
	public Long getListCount(String statementName, Map<String,?> param) throws Exception
	{
		try {
			Object object = getJdbcTemplate().queryForObject(getSqlName(statementName), param);
			if (object != null) {
				return (Long) object;
			}
			return 0L;
		} catch (Exception e) {
			throw new Exception(String.format("查询分页记录总数出错！ %s", e.getMessage()));
		}
	}
}